/*
MIT License

Copyright (c) 2022 guo-yichen,chen-chaochen@Easylosu

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 
SOFTWARE.

*/
#include<iostream>
#include<string>
#include<vector>
#include"libstring.hpp"
using namespace std;
string losu_string_strrt;
/* 
U+2E80 - U+2EF3 : 0xE2 0xBA 0x80 - 0xE2 0xBB 0xB3      共 115 个  
U+2F00 - U+2FD5 : 0xE2 0xBC 0x80 - 0xE2 0xBF 0x95      共 213 个  
U+3005 - U+3029 : 0xE3 0x80 0x85 - 0xE3 0x80 0xA9      共 36 个  
U+3038 - U+4DB5 : 0xE3 0x80 0xB8 - 0xE4 0xB6 0xB5      共 7549 个  
U+4E00 - U+FA6A : 0xE4 0xB8 0x80 - 0xEF 0xA9 0xAA      共 44138 个  
U+FA70 - U+FAD9 : 0xEF 0xA9 0xB0 - 0xEF 0xAB 0x99      共 105 个  
*/
/*
U+20000 - U+2FA1D : 0xF0 0xA0 0x80 0x80 - 0xF0 0xAF 0xA8 0x9D
*/
int mylength(string str){
    int rt=0;
    for(int i=0;i<str.length();i++){
        if(str[i]>=(char)0xe2&&str[i]<=(char)0xef)  i=i+2;
        else if(str[i]==(char)0xf0) i=i+3;
        rt++;
    }
    return rt;
}
string mymid(string str,int pos,int len){
    int npos=1,nlen=0;
    int i;
    string rt;
    for( i=0;npos!=pos;i++){
        if(i>=str.length())
            return "";
        if(str[i]>=(char)0xe2&&str[i]<=(char)0xef)  i=i+2;
        else if(str[i]==(char)0xf0) i=i+3;
        npos++;
    }
    for(;nlen!=len;i++){
        if(i>=str.length())
            nlen = len-1;
        rt+=str[i];
        if(str[i]>=(char)0xe2&&str[i]<=(char)0xef){
            i++;rt+=str[i];
            i++;rt+=str[i];
        }else if(str[i]==(char)0xf0){
            i++;rt+=str[i];
            i++;rt+=str[i];
            i++;rt+=str[i];
        }
        
        nlen++;
    }
    return rt;
    

}
string mytoupper(string str){
    string rt;
    for(int i=0;i<str.size();i++){
        if(str[i]>='a'&&str[i]<='z')
            rt+=(str[i]-32);
        else if(str[i]>=(char)0xe2&&str[i]<=(char)0xef){
            rt+=str[i];
            i++;rt+=str[i];
            i++;rt+=str[i];
        }
        else if(str[i]==(char)0xf0){
            rt+=str[i];
            i++;rt+=str[i];
            i++;rt+=str[i];
            i++;rt+=str[i];
        }else rt+= str[i];
    }
    return rt;
}
string mytolower(string str){
    string rt;
    for(int i=0;i<str.size();i++){
        if(str[i]>='A'&&str[i]<='Z')
            rt+=(str[i]+32);
        else if(str[i]>=(char)0xe2&&str[i]<=(char)0xef){
            rt+=str[i];
            i++;rt+=str[i];
            i++;rt+=str[i];
        }
        else if(str[i]==(char)0xf0){
            rt+=str[i];
            i++;rt+=str[i];
            i++;rt+=str[i];
            i++;rt+=str[i];
        }else rt+= str[i];
    }
    return rt;
}
string mymiror(string str){
    string rt;
    for(int i=0;i<str.length();i++){
        if(str[i]>=(char)0xe2&&str[i]<=(char)0xef){
            rt = str.substr(i,1)+str.substr(i+1,1)+str.substr(i+2,1)+rt;
            i=i+2;
        }else if(str[i]==(char)0xf0){
            rt = str.substr(i,1)+str.substr(i+1,1)+str.substr(i+2,1)+str.substr(i+3,1)+rt;
            i=i+3;
        }else rt = str[i]+rt;
    }
    return rt;
}
inline string mid(string a,long start_pos,long len_pos){
    if (start_pos > a.length()){
        return "";
    }
	return a.substr(start_pos - 1,len_pos);
}
inline string myreplace(string src,string old_value,string new_value){
    long i;
	string rep;
	i = 1;
	while(1){
		if (mid(src,i,old_value.length()) == old_value ){
			i = i + old_value.length() -1 ;
			rep = rep + new_value ;
		}else{
			rep = rep + mid(src,i,1) ;
		}
		i++;
		if (i > src.length()){
			rep = rep + mid(src,i,1) ;
			break;
		}
	}
	return rep;
}

extern "C"{
    LNI losu_string_len(LNI _str){
        string str = _str;
        int rt=0;
        losu_string_rt[0]='\0';
        for(int i=0;i<str.length();i++){
            if(str[i]>=(char)0xe2&&str[i]<=(char)0xef)  i=i+2;
            else if(str[i]==(char)0xf0) i=i+3;
            rt++;
        }
        sprintf(losu_string_rt,"%d",rt);
        return losu_string_rt;
    }
    LNI losu_string_asciilen(LNI _str){
        string str = _str;
        losu_string_strrt = to_string(str.length());
        return (char*)losu_string_strrt.c_str();
    }
    LNI losu_string_mid(LNI _str,LNI _spos,LNI _len){
        losu_string_strrt = mymid(_str,atoi(_spos),atoi(_len));
        return (char*)losu_string_strrt.c_str();
    }
    LNI losu_string_find(LNI _str,LNI _obj){
        losu_string_rt[0]='\0';
        string str = _str,obj=_obj;
        for(int i = 1;i<=str.length()-obj.length()+1;i++){
            if(mymid(str,i,mylength(obj))==obj){
                sprintf(losu_string_rt,"%d",i);
                return losu_string_rt;
            }
        }
        sprintf(losu_string_rt,"%d",-1);
        return losu_string_rt;
    }
    LNI losu_string_reverse(LNI _str){
        string str = _str;
        string rt; 
        for(int i=0;i<str.length();i++){
            if(str[i]>=(char)0xe2&&str[i]<=(char)0xef){
                rt = str.substr(i,1)+str.substr(i+1,1)+str.substr(i+2,1)+rt;
                i=i+2;
            }else if(str[i]==(char)0xf0){
                rt = str.substr(i,1)+str.substr(i+1,1)+str.substr(i+2,1)+str.substr(i+3,1)+rt;
                i=i+3;
            }else rt = str[i]+rt;
        }
        losu_string_strrt = rt;
        return (char*)losu_string_strrt.c_str();
    }
    LNI losu_string_toupper(LNI _str){
        string str= _str;
        string rt;
        for(int i=0;i<str.size();i++){
            if(str[i]>='a'&&str[i]<='z')
                rt+=(str[i]-32);
            else if(str[i]>=(char)0xe2&&str[i]<=(char)0xef){
                rt+=str[i];
                i++;rt+=str[i];
                i++;rt+=str[i];
            }else if(str[i]==(char)0xf0){
                rt+=str[i];
                i++;rt+=str[i];
                i++;rt+=str[i];
                i++;rt+=str[i];
            }else rt+= str[i];
        }
        losu_string_strrt = rt;
        return (char*)losu_string_strrt.c_str();
    }
    LNI losu_string_tolower(LNI _str){
        string str = _str;
        string rt;
        for(int i=0;i<str.size();i++){
            if(str[i]>='A'&&str[i]<='Z')
                rt+=(str[i]+32);
            else if(str[i]>=(char)0xe2&&str[i]<=(char)0xef){
                rt+=str[i];
                i++;rt+=str[i];
                i++;rt+=str[i];
            }else if(str[i]==(char)0xf0){
                rt+=str[i];
                i++;rt+=str[i];
                i++;rt+=str[i];
                i++;rt+=str[i];
            }else rt+= str[i];
        }
        losu_string_strrt = rt;
        return (char*)losu_string_strrt.c_str();
    }
    LNI losu_string_createstr(LNI _str,LNI _num){
        int num = atoi(_num);
        losu_string_strrt="";
        for(int i =0;i<num;i++)
            losu_string_strrt+=_str;
        //cout<<losu_string_strrt<<endl;
        return (char*)losu_string_strrt.c_str();
    }
    LNI losu_string_countnum(LNI _str,LNI _obj){
        losu_string_rt[0]='\0';
        string str = _str,obj=_obj;
        int rt=0;
        for(int i = 1;i<=mylength(str);i++){
            if(mymid(str,i,mylength(obj))==obj) rt++;
        }
        sprintf(losu_string_rt,"%d",rt);
        return losu_string_rt;
    }
    LNI losu_string_asciimid(LNI _str,LNI _pos,LNI _len){
        string str = _str;
        losu_string_strrt = str.substr(atoi(_pos)-1,atoi(_len));
        return (char*)losu_string_strrt.c_str();
    }
    LNI losu_string_replace(LNI str,LNI ostr,LNI nstr){
        losu_string_strrt = myreplace(str,ostr,nstr);
        return (char*)losu_string_strrt.c_str();
    }
    LNI losu_string_ascii(LNI s){
        losu_string_rt[0]='\0';
        sprintf(losu_string_rt,"%d",(int)((unsigned char)(s[0])));
        return losu_string_rt;
    }
    LNI losu_string_char(LNI num){
        losu_string_rt[0]='\0';
        sprintf(losu_string_rt,"%c",(unsigned char)(atoi(num)));
        return losu_string_rt;
    }
}

